package com.ezcoding.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ezcoding.dao.CompanyDao;
import com.ezcoding.dao.MessageDao;
import com.ezcoding.dao.UserDao;
import com.ezcoding.dao.UserRelationDao;
import com.ezcoding.model.*;
import com.ezcoding.utils.StatusUtil;
import com.ezcoding.utils.Tools;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UserRelationService {
    private static UserRelationService instance = new UserRelationService();

    public final static int BUILD_SUB_ACCOUNT = 1;
    public final static int CHANGE_USER_RELATION = 2;

    private final static int PLATFORM = 1;
    private final static int NON_PLATFORM = 0;

    public static UserRelationService getInstance() {
        return instance;
    }

    public Map<String, Object> queryPlatformUser(String username, String companyId) {
        if (Tools.checkParaIsInValidate(username, companyId)) {
            return StatusUtil.getFailedStatusWithMessage("参数无效！");
        }

        User user = UserDao.dao.getUserByUsername(username);

        if (user == null || !user.getCompanyId().equals(companyId)) {
            return StatusUtil.getFailedStatusWithMessage("查找的用户不存在！");
        }

        Company company = CompanyDao.dao.getCompanyByCompanyId(companyId);

        Map<String, Object> res = new HashMap<>();
        Map<String, Object> data = new HashMap<>();

        data.put("user", user);
        data.put("company", company);
        res.put("data", data);

        return StatusUtil.getSuccessStatusWithMessage(res, "查询成功！");
    }

    public Map<String, Object> addPlatformUser(String sourceUsername, String targetUsername, String typeStr) {
        if (Tools.checkParaIsInValidate(sourceUsername, targetUsername, typeStr)) {
            return StatusUtil.getFailedStatusWithMessage("参数无效！");
        }

        int type = Tools.parseNatureInteger(typeStr);
        if (type < 1 || type > 3) {
            return StatusUtil.getFailedStatusWithMessage("类型参数错误！");
        }

        if (sourceUsername.equals(targetUsername)) {
            return StatusUtil.getFailedStatusWithMessage("不能添加当前用户！");
        }

        User sourceUser = UserDao.dao.getUserByUsername(sourceUsername);
        User targetUser = UserDao.dao.getUserByUsername(targetUsername);

        if (sourceUser == null || targetUser == null) {
            return StatusUtil.getFailedStatusWithMessage("用户不存在！");
        }

        UserRelation relation = UserRelationDao.dao.getUserRelation(sourceUsername, targetUsername, type);

        typeStr = type == UserRelation.RELATION_TYPE_CLIENT ? "客户" : "供应商";

        if (sourceUser.getCompanyId().equals(targetUser.getCompanyId())) {
            return StatusUtil.getFailedStatusWithMessage("不能添加自己的同事为" + typeStr + "！");
        }

        if (relation != null) {
            //对方和自己已经存在请求关系
            return StatusUtil.getFailedStatusWithMessage("该用户已经是您的" + typeStr + "！");
        }

        int reverseType = type == UserRelation.RELATION_TYPE_CLIENT ? UserRelation.RELATION_TYPE_GIVER : UserRelation.RELATION_TYPE_CLIENT;
        relation = getUserRelation(sourceUser, targetUser, type, 1);
        UserRelation relationReverse = getUserRelation(targetUser, sourceUser, reverseType, PLATFORM);

        return StatusUtil.getStatus(relation.save() && relationReverse.save(), "添加成功！", "添加失败！");
    }

    public Map<String, Object> addNonPlatformUser(
            String username,
            String typeStr,
            String nickName,
            String contact,
            String tel,
            String remark,
            String primaryDirectory,
            String secondaryDirectory) {

        if (Tools.checkParaIsNullPoint(tel, remark, secondaryDirectory)) {
            return StatusUtil.getFailedStatusWithMessage("参数无效！");
        }

        if (Tools.checkParaIsInValidate(username, nickName, contact, primaryDirectory)) {
            return StatusUtil.getFailedStatusWithMessage("参数无效！");
        }

        User sourceUser = UserDao.dao.getUserByUsername(username);
        if (sourceUser == null) {
            return StatusUtil.getFailedStatusWithMessage("用户不存在！");
        }

        int type = Tools.parseNatureInteger(typeStr);
        if (type < 1 || type > 3) {
            return StatusUtil.getFailedStatusWithMessage("类型参数错误！");
        }

        Company targetCompany = getTargetCompany(sourceUser, nickName);

        User targetUser = getTargetUser(sourceUser, targetCompany, contact, tel);

        if (!(targetCompany.save() && targetUser.save())) {
            StatusUtil.getFailedStatusWithMessage("添加失败");
        }

        UserRelation relation = getUserRelation(sourceUser, targetUser, type, NON_PLATFORM);

        relation.setRemark(remark);
        relation.setPrimaryDirectory(primaryDirectory);
        relation.setSecondaryDirectory(secondaryDirectory);

        return StatusUtil.getStatus(relation.save(), "添加成功！", "添加失败！");
    }

    private Company getTargetCompany(User sourceUser, String companyName) {
        Company company = new Company();

        company.setCompanyId(sourceUser.getCompanyId() + "-" + Tools.getRandomId());
        company.setCompanyName(companyName);

        return company;
    }

    private User getTargetUser(User sourceUser, Company targetCompany, String nickName, String tel) {
        User targetUser = new User();

        targetUser.setUsername(sourceUser.getUsername() + "-" + Tools.getRandomId());
        targetUser.setCompanyId(targetCompany.getCompanyId());
        targetUser.setNickName(nickName);
        targetUser.setTel(tel);
        targetUser.setIsPlatform(0);

        return targetUser;
    }

    private UserRelation getUserRelation(User sourceUser, User targetUser, int type, int isPlatform) {
        UserRelation userRelation = new UserRelation();
        Company company = CompanyDao.dao.getCompanyByCompanyId(targetUser.getCompanyId());

        userRelation.setSourceUsername(sourceUser.getUsername());
        userRelation.setSourceCompanyId(sourceUser.getCompanyId());
        userRelation.setTargetUsername(targetUser.getUsername());
        userRelation.setTargetCompanyId(targetUser.getCompanyId());
        userRelation.setType(type);
        userRelation.setIsPlatform(isPlatform);
        userRelation.setNickName(company.getCompanyName());
        userRelation.setNickNamePinyin(Tools.toHanyuPinyin(company.getCompanyName()));
        userRelation.setContact(targetUser.getNickName());
        userRelation.setContactPinyin(Tools.toHanyuPinyin(targetUser.getNickName()));
        userRelation.setTel(targetUser.getTel());
        userRelation.setPrimaryDirectory(type == UserRelation.RELATION_TYPE_CLIENT ? "所有客户" : "所有供应商");

        return userRelation;
    }

    public Map<String, Object> getUserRelationsByUsernameAndType(String username, String typeStr) {
        if (Tools.checkParaIsInValidate(username)) {
            return StatusUtil.getFailedStatusWithMessage("参数无效！");
        }

        User user = UserDao.dao.getUserByUsername(username);

        if (user == null) {
            return StatusUtil.getFailedStatusWithMessage("用户不存在！");
        }

        List<UserRelation> relations;

        int type = Tools.parseNatureInteger(typeStr);
        switch (type) {
            case UserRelation.RELATION_TYPE_CLIENT:
                relations = UserRelationDao.dao.getClientsByUsername(username);
                break;
            case UserRelation.RELATION_TYPE_GIVER:
                relations = UserRelationDao.dao.getGiversByUsername(username);
                break;
            default:
                return StatusUtil.getFailedStatusWithMessage("类型参数错误！");
        }

        Map<String, Object> res = new HashMap<>();
        Map<String, Object> data = new HashMap<>();

        data.put("relations", relations);
        res.put("data", data);

        return StatusUtil.getSuccessStatusWithMessage(res, "获取成功！");
    }

    public Map<String, Object> queryUserRelationDetail(String username, String companyId) {
        if (Tools.checkParaIsInValidate(username, companyId)) {
            return StatusUtil.getFailedStatusWithInvalidParaMessage();
        }

        Company company = CompanyDao.dao.getCompanyByCompanyId(companyId);
        if (company == null) {
            return StatusUtil.getFailedStatusWithMessage("企业不存在！");
        }

        User user = UserDao.dao.getUserByUsername(username);
        if (user == null) {
            return StatusUtil.getFailedStatusWithMessage("用户不存在！");
        }

        Map<String, Object> res = new HashMap<>();
        Map<String, Object> data = new HashMap<>();

        data.put("company", company);
        data.put("user", user);
        res.put("data", data);

        return StatusUtil.getSuccessStatusWithMessage(res, "获取成功！");
    }

    public Map<String, Object> updateUserRelation(String sourceUsername, String targetUsername, String typeStr, int updateType) {
        if (Tools.checkParaIsInValidate(sourceUsername, targetUsername, typeStr)) {
            return StatusUtil.getFailedStatusWithInvalidParaMessage();
        }

        int type = Tools.parseNatureInteger(typeStr);

        if (type == -1) {
            return StatusUtil.getFailedStatusWithMessage("类型参数错误");
        }

        UserRelation relation = UserRelationDao.dao.getUserRelation(sourceUsername, targetUsername, type);

        if (relation == null) {
            return StatusUtil.getFailedStatusWithMessage("用户关系不存在！");
        }

        int anotherType = type == UserRelation.RELATION_TYPE_CLIENT ? UserRelation.RELATION_TYPE_GIVER : UserRelation.RELATION_TYPE_CLIENT;
        UserRelation relationAnother = UserRelationDao.dao.getUserRelation(targetUsername, sourceUsername, anotherType);

        switch (updateType) {
            case BUILD_SUB_ACCOUNT:
                relation.setHasSubAccount(1);
                if (relationAnother != null) {
                    relationAnother.setHasSubAccount(1);
                    relationAnother.update();
                }
                return StatusUtil.getStatus(relation.update(), "建立成功！", "建立失败！");
            case CHANGE_USER_RELATION:
                int relationType = relation.getType();

                if (relationType != UserRelation.RELATION_TYPE_CLIENT && relationType != UserRelation.RELATION_TYPE_GIVER) {
                    return StatusUtil.getFailedStatusWithMessage("已为客供关系无需修改");
                }

                if (relationAnother == null) {
                    System.out.println("another relation is null");
                    relationAnother = UserRelation.getInverseTypeRelation(relation);
                    relationAnother.save();
                }

                relation.setType(UserRelation.RELATION_TYPE_ALL);
                relationAnother.setType(UserRelation.RELATION_TYPE_ALL);

                return StatusUtil.getStatus(relation.update() && relationAnother.update(), "修改成功", "修改失败");
            default:
                return StatusUtil.getFailedStatusWithMessage("服务器错误！");
        }
    }

    public Map<String, Object> updateUserRelation(
            String sourceUsername,
            String targetUsername,
            String typeStr,
            String urClientName,
            String urContact,
            String urTel,
            String urRemark,
            String urCredit,
            String urPrimaryDirectory,
            String urSecondaryDirectory,
            String userNickName,
            String userPosition,
            String userTel,
            String userMobile,
            String userQQ,
            String userWechat,
            String companyCompanyName,
            String companyContact,
            String companyTel,
            String companyFax,
            String companyWebsite,
            String companyEmail,
            String companyProvince,
            String companyCity,
            String companyDistrict,
            String companyAddress,
            String companyAccount,
            String companyIntroduction,
            String companyTicketCompanyName,
            String companyTaxNum,
            String companyBank,
            String companyTicketAccount,
            String companyTicketTel,
            String companyTicketAddress) {
        if (Tools.checkParaIsInValidate(sourceUsername, targetUsername, typeStr)) {
            return StatusUtil.getFailedStatusWithInvalidParaMessage();
        }

        if (Tools.checkParaIsNullPoint(
                urClientName,
                urContact,
                urTel,
                urRemark,
                urCredit,
                urPrimaryDirectory,
                urSecondaryDirectory,
                userNickName,
                userPosition,
                userTel,
                userMobile,
                userQQ,
                userWechat,
                companyCompanyName,
                companyContact,
                companyTel,
                companyFax,
                companyWebsite,
                companyEmail,
                companyProvince,
                companyCity,
                companyDistrict,
                companyAddress,
                companyAccount,
                companyIntroduction,
                companyTicketCompanyName,
                companyTaxNum,
                companyBank,
                companyTicketAccount,
                companyTicketTel,
                companyTicketAddress)) {
            return StatusUtil.getFailedStatusWithInvalidParaMessage();
        }

        int credit = Tools.parseNatureInteger(urCredit);
        int type = Tools.parseNatureInteger(typeStr);

        if (credit < 0) {
            return StatusUtil.getFailedStatusWithMessage("信用额度为非负整数！");
        }

        if (type != UserRelation.RELATION_TYPE_CLIENT && type != UserRelation.RELATION_TYPE_GIVER) {
            return StatusUtil.getFailedStatusWithMessage("类型参数错误！");
        }

        UserRelation relation = UserRelationDao.dao.getUserRelation(sourceUsername, targetUsername, type);
        int anotherType = type == UserRelation.RELATION_TYPE_CLIENT ? UserRelation.RELATION_TYPE_GIVER : UserRelation.RELATION_TYPE_CLIENT;
        UserRelation relationAnother = UserRelationDao.dao.getUserRelation(sourceUsername, targetUsername, anotherType);

        if (relation == null) {
            return StatusUtil.getFailedStatusWithMessage("用户关系不存在！");
        }

        if (relation.getIsPlatform() == PLATFORM) {
            relation.setRemark(urRemark);
            relation.setCredit(credit);
            relation.setPrimaryDirectory(urPrimaryDirectory);
            relation.setSecondaryDirectory(urSecondaryDirectory);
            if (relationAnother != null) {
                relationAnother.setRemark(urRemark);
                relationAnother.setCredit(credit);
                relationAnother.update();
            }

            return StatusUtil.getStatus(relation.update(), "保存成功！", "保存失败！");
        }

        User targetUser = UserDao.dao.getUserByUsername(targetUsername);
        if (targetUser == null) {
            return StatusUtil.getFailedStatusWithMessage("用户基本信息不存在！");
        }

        Company company = CompanyDao.dao.getCompanyByCompanyId(targetUser.getCompanyId());
        if (company == null) {
            return StatusUtil.getFailedStatusWithMessage("用户企业信息不存在！");
        }

        relation.updateInfo(
                urClientName,
                urContact,
                urTel,
                urRemark,
                credit);
        relation.setPrimaryDirectory(urPrimaryDirectory);
        relation.setSecondaryDirectory(urSecondaryDirectory);
        if (relationAnother != null) {
            relationAnother.updateInfo(
                    urClientName,
                    urContact,
                    urTel,
                    urRemark,
                    credit);
            relationAnother.update();
        }

        targetUser.setNickName(userNickName);
        targetUser.setPosition(userPosition);
        targetUser.setTel(userTel);
        targetUser.setMobile(userMobile);
        targetUser.setQQ(userQQ);
        targetUser.setWechat(userWechat);

        company.updateInfo(
                companyCompanyName,
                companyContact,
                companyTel,
                companyFax,
                companyWebsite,
                companyEmail,
                companyProvince,
                companyCity,
                companyDistrict,
                companyAddress,
                companyAccount,
                companyIntroduction,
                companyTicketCompanyName,
                companyTaxNum,
                companyBank,
                companyTicketAccount,
                companyTicketTel,
                companyTicketAddress);

        return StatusUtil.getStatus(
                relation.update() && targetUser.update() && company.update(),
                "保存成功！",
                "保存失败！");
    }

    public Map<String, Object> uploadUserRelation(String username, String typeStr, String relationsStr) {
        if (Tools.checkParaIsInValidate(username, typeStr, relationsStr)) {
            return StatusUtil.getFailedStatusWithInvalidParaMessage();
        }

        int type = Tools.parseNatureInteger(typeStr);
        if (type < 1 || type > 3) {
            return StatusUtil.getFailedStatusWithMessage("类型参数错误！");
        }

        User sourceUser = UserDao.dao.getUserByUsername(username);
        if (sourceUser == null) {
            return StatusUtil.getFailedStatusWithMessage("用户不存在！");
        }

        JSONArray array = JSONArray.parseArray(relationsStr);
        for (int i = 0; i < array.size(); i++) {
            JSONObject obj = array.getJSONObject(i);
            String nickName = obj.getString("nick_name");
            String contact = obj.getString("contact");
            String tel = obj.getString("tel");
            String remark = obj.getString("remark");
            String primaryDirectory = obj.getString("primary_directory");
            String secondaryDirectory = obj.getString("secondary_directory");

            Company targetCompany = getTargetCompany(sourceUser, nickName);
            User targetUser = getTargetUser(sourceUser, targetCompany, contact, tel);

            if (!(targetCompany.save() && targetUser.save())) {
                return StatusUtil.getFailedStatusWithMessage("第" + (i + 1) + "条用户关系添加失败！");
            }

            UserRelation relation = getUserRelation(sourceUser, targetUser, type, NON_PLATFORM);
            relation.setRemark(remark);
            relation.setPrimaryDirectory(primaryDirectory);
            relation.setSecondaryDirectory(secondaryDirectory);

            if (!relation.save()) {
                return StatusUtil.getFailedStatusWithMessage("第" + (i + 1) + "条用户关系建立失败！");
            }
        }

        return StatusUtil.getSuccessStatusWithMessage("上传成功");
    }

    public Map<String, Object> adjustUserRelationFinance(
            String sourceUsername,
            String targetUsername,
            String relatedMessageId,
            int relationType,
            double oldTicketIn,
            double oldTicketOut,
            double oldMoneyIn,
            double oldMoneyOut,
            double ticketIn,
            double ticketOut,
            double moneyIn,
            double moneyOut) {
        if (Tools.checkParaIsInValidate(sourceUsername, targetUsername)) {
            return StatusUtil.getFailedStatusWithInvalidParaMessage();
        }

        UserRelation relation = UserRelationDao.dao.getUserRelation(sourceUsername, targetUsername, relationType);

        User user = UserDao.dao.getUserByUsername(sourceUsername);

        if (user == null) {
            return StatusUtil.getFailedStatusWithMessage("用户不存在！");
        }

        if (relation == null) {
            return StatusUtil.getFailedStatusWithMessage("用户关系不存在！");
        }

        if (!Tools.doubleIsEqual(relation.getTicketIn(), oldTicketIn) ||
                !Tools.doubleIsEqual(relation.getTicketOut(), oldTicketOut) ||
                !Tools.doubleIsEqual(relation.getMoneyIn(), oldMoneyIn) ||
                !Tools.doubleIsEqual(relation.getMoneyOut(), oldMoneyOut)) {
            return StatusUtil.getFailedStatusWithMessage("本地数据与服务器数据不符，请更新本地客户/供应商数据！");
        }

        relation.setTicketIn(relation.getTicketIn() + ticketIn);
        relation.setTicketOut(relation.getTicketOut() + ticketOut);
        relation.setMoneyIn(relation.getMoneyIn() + moneyIn);
        relation.setMoneyOut(relation.getMoneyOut() + moneyOut);

        Message relatedMessage = MessageDao.dao.getMessageById(targetUsername, relatedMessageId);

        boolean isBuildMsg = true;
        if (relatedMessage != null) {
            isBuildMsg = false;
            if (!relatedMessage.delete()) {
                return StatusUtil.getFailedStatusWithMessage("关联消息删除失败！");
            }
        }

        String remark;
        if (ticketIn != 0 || ticketOut != 0) {
            remark = ticketIn != 0 ? "应收发票调整" : "应开发票调整";
        } else {
            remark = moneyIn != 0 ? "应收货款调整" : "应付货款调整";
        }

        Dingdan dingdan = new Dingdan(
                relation,
                ticketIn,
                ticketOut,
                moneyIn,
                moneyOut);
        DingdanDetail dingdanDetail = new DingdanDetail(dingdan);

        if (!dingdan.save() || !dingdanDetail.save()) {
            return StatusUtil.getFailedStatusWithMessage("票款调整订单记录建立失败！");
        }

        if (!relation.update()) {
            return StatusUtil.getFailedStatusWithMessage("用户关系更新失败！");
        }

        if (isBuildMsg) {
            //建立消息
            Message message = new Message(
                    sourceUsername,
                    targetUsername,
                    relationType,
                    ticketIn,
                    ticketOut,
                    moneyIn,
                    moneyOut,
                    Message.MESSAGE_TYPE_TICKET_ADJUST,
                    user.getNickName(),
                    remark);

            if (!message.save()) {
                return StatusUtil.getFailedStatusWithMessage("消息建立失败！");
            }
        }

        return StatusUtil.getSuccessStatusWithMessage("票款调整结算成功！");
    }

    public Map<String, Object> deleteUserRelation(
            String sourceUsername,
            String targetUsername,
            int relationType) {
        if (Tools.checkParaIsInValidate(sourceUsername, targetUsername)) {
            return StatusUtil.getFailedStatusWithInvalidParaMessage();
        }

        UserRelation relation = UserRelationDao.dao.getUserRelation(sourceUsername, targetUsername, relationType);

        if (relation == null) {
            return StatusUtil.getFailedStatusWithMessage("用户关系不存在！");
        }

        if (relation.getIsPlatform() != 0) {
            return StatusUtil.getFailedStatusWithMessage("不能删除平台用户！");
        }

        if (relation.getTicketIn() != 0 ||
                relation.getTicketOut() != 0 ||
                relation.getMoneyIn() != 0 ||
                relation.getMoneyOut() != 0 ||
                relation.getPreTicketIn() != 0 ||
                relation.getPreTicketOut() != 0 ||
                relation.getPreMoneyIn() != 0 ||
                relation.getPreMoneyOut() != 0) {
            return StatusUtil.getFailedStatusWithMessage("客户或供应商的票款或货款金额不为0！");
        }

        if (!relation.delete()) {
            return StatusUtil.getFailedStatusWithMessage("删除失败！");
        }

        return StatusUtil.getSuccessStatusWithMessage("删除成功！");
    }
}
